package com.hotelsystem.reservation.creators;

import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

import com.hotelsystem.reservations.clientvalidation.ReservationValidator;
import com.hotelsystem.reservations.reservations.Reservation;
import com.hotelsystem.reservations.rooms.Room;

/**
 * 
 * @author Hristo Hristov
 * 
 */
public class ReservationCreator {

    private InputStream inputStream;
    private SimpleDateFormat simpleDateFormat;
    private Scanner scanner;

    /**
     * Optional input stream object
     * 
     * @param inputStream
     */
    public ReservationCreator(InputStream inputStream) {
        super();
        this.inputStream = inputStream;
        simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        scanner = new Scanner(this.inputStream);
    }

    /**
     * Default input stream will be the command line
     */
    public ReservationCreator() {
        this(System.in);
    }

    /** Class that is used for attributes validation */
    private abstract class ValidatorFunction {
        private String failureMessage;

        public ValidatorFunction(String failureMessage) {
            this.failureMessage = failureMessage;
        }

        public String getFailureMessage() {
            return this.failureMessage;
        }

        public abstract boolean doValidation(Date date);
    }

    /**
     * Simply creates Reservation object from input stream (default is command
     * line)
     * 
     * @return Reservation, could return null in case of invalid input data
     */
    public Reservation createReservation() {
        // prompt for reservation startdate
        Date startdate = createStartDate(new ValidatorFunction("Date should be yyyy-MM-dd HH:mm format!") {

            @Override
            public boolean doValidation(Date date) {
                return new ReservationValidator().validateStartDate(date);
            }
        });

        // prompt for reservation enddate
        String reservationEnddate = readScanner("Enter reservation enddate: ");
        Date enddate = tryParseDate(reservationEnddate, "Invalid start date");

        // prompt for room number
        String roomNumber = readScanner("Enter room number: ");

        // TODO V a l i d a t e !!!
        // before creating Reservation instance

        Reservation reservation = new Reservation();
        Room room = new Room();
        room.setRoomNumber(Integer.parseInt(roomNumber));
        reservation.setStartDate(startdate);
        reservation.setEndDate(enddate);
        reservation.setRoom(room);

        return reservation;
    }

    private Date createStartDate(ValidatorFunction validator) {
        Date startdate;
        while (true) {
            String reservationStartdate = readScanner("Enter reservation startdate: ");
            startdate = tryParseDate(reservationStartdate, "Invalid start date");

            if (startdate != null && validator.doValidation(startdate)) {
                break;
            } else {
                System.out.println(validator.getFailureMessage());
            }
        }
        return startdate;
    }

    private String readScanner(String displayMessage) {
        System.out.print(displayMessage);
        return scanner.nextLine();
    }

    private Date tryParseDate(String dateToParse, String errorMessage) {
        Date enddate;
        try {
            enddate = simpleDateFormat.parse(dateToParse);
        } catch (ParseException e) {
            System.out.println(errorMessage);
            return null;
        }
        return enddate;
    }

}
